package com.v9.flow.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.v9.common.core.service.DefaultService;
import com.v9.common.dto.UserDto;
import com.v9.common.exception.BizException;
import com.v9.flow.domain.FlowInfo;
import com.v9.flow.domain.FlowSponsor;
import com.v9.flow.mapper.FlowInfoMapper;
import com.v9.flow.mapper.FlowSponsorMapper;
import com.v9.flow.service.FlowBizTypeService;
import com.v9.flow.service.FlowInfoService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.DeploymentBuilder;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.task.Task;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

/**
 * 参数配置 服务层实现
 *
 * @author shilun
 */
@Service
public class FlowInfoServiceImpl extends DefaultService<FlowInfoMapper, FlowInfo> implements FlowInfoService {
    @Resource
    private ProcessEngine processEngine;

    @Resource
    private FlowBizTypeService flowBizTypeService;
    @Resource
    private RepositoryService repositoryService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private TaskService taskService;

    @Resource
    private FlowSponsorMapper flowSponsorMapper;

    @Override
    public void deployment(Long id) {
        FlowInfo info = findById(id);
        DeploymentBuilder deployment = processEngine.getRepositoryService().createDeployment();
        DeploymentBuilder name = deployment.addString(info.getCode() + ".bpmn20.xml", info.getContent()).name(info.getCode());
        Deployment deploy1 = name.deploy();
        save(id, "depStatus", true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insert(FlowInfo flowInfo, List<FlowSponsor> sponsors) {
        insert(flowInfo);
        sponsors.forEach(item -> {
            FlowSponsor entity = new FlowSponsor();
            entity.setRefId(item.getRefId());
            entity.setType(item.getType());
            entity.setFlowId(flowInfo.getId());
            flowSponsorMapper.insert(entity);
        });
    }

    @Override
    public void save(FlowInfo info, List<FlowSponsor> sponsors) {
        updateById(info);
        QueryWrapper<FlowSponsor> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("flow_id", info.getId());
        List<FlowSponsor> flowSponsors = flowSponsorMapper.selectList(queryWrapper);

        Collection<FlowSponsor> addList = CollectionUtils.subtract(sponsors, flowSponsors);
        addList.forEach(item->{
            FlowSponsor data=new FlowSponsor();
            data.setType(item.getType());
            data.setRefId(item.getRefId());
            data.setFlowId(info.getId());
            flowSponsorMapper.insert(data);
        });
        Collection<FlowSponsor> delList = CollectionUtils.subtract(flowSponsors, sponsors);
        delList.forEach(item->{
            QueryWrapper<FlowSponsor> delQuery=new QueryWrapper<>();
            delQuery.eq("ref_id",item.getRefId());
            delQuery.eq("flow_id",item.getFlowId());
            delQuery.eq("type",item.getType());
            flowSponsorMapper.delete(delQuery);
        });

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveContent(Long id, String flowContent) {
        FlowInfo one = findById(id);
        if (one == null) {
            throw new BizException("data.error");
        }
        if (one.getDepStatus().booleanValue() == true) {
            throw new BizException("已发布的流程，不能修改");
        }
        one = new FlowInfo();
        one.setId(id);
        one.setContent(flowContent);
        updateById(one);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void instance(String code, UserDto user, Map<String, Object> formData) {
        FlowInfo info = new FlowInfo();
        info.setCode(code);
        info = findByOne(info);
        if (info == null) {
            throw new BizException("201", "非法操作");
        }
        //流程常量
        String createPin = user.getPin();
        String createByUserName = user.getUsername();
        Date createByTime = new Date();
        String title = info.getName();
        if (formData.get("title") != null) {
            title = formData.get("title").toString();
        }
        //流程概要信息
        Map<String, Object> params = new HashMap<>(4);
        params.put("title", title);
        params.put("createByPin", createPin);
        params.put("createByName", createByUserName);
        params.put("createByTime", createByTime);
        if (params.size() != 4) {
            throw new BizException("非法操作");
        }
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();
        processDefinitionQuery.latestVersion();
        processDefinitionQuery.processDefinitionKey(code);
        List<ProcessDefinition> list = processDefinitionQuery.list();
        String id = null;
        for (ProcessDefinition processDefinition : list) {
            id = processDefinition.getId();
        }
        formData.putAll(params);
        //实例化流程
        org.activiti.engine.runtime.ProcessInstance processInstance = runtimeService.startProcessInstanceById(id, formData);
        //绑定首次表单数据到实例变量
        List<Task> taskList = taskService.createTaskQuery()//创建查询对象
                .processInstanceId(processInstance.getId())//通过流程实例id来查询当前任务
                .taskUnassigned().list();
        Task task = taskList.get(0);
        task.setAssignee(user.getUsername());
        taskService.complete(task.getId(), formData);
    }

}
